<?php
/**
 * A Connection class that provides a single interface for commonly 
 * needed operations 
 * 
 * @copyright Copyright (c) 2010 Jeff. {@link http://www.i9tiao.com}
 * @package model
 */
class Connection
{
    /**
     * @var Connection
     */
	private static $conn = NULL;
	
    /**
     * @var slave_db Connection
     */
	private $r = NULL;
    /**
     * @var master_db Connection
     */
	public $w = NULL;
    /**
     * @var slave_db Connection Count
     */
	private $count_r=0;
	/**
     * @var master_db Connection Count
     */
	private $count_w=0;
	
	/**
     * construct
     */
	private function __construct()
	{
		
	}
	
	private function __clone()
	{
	}
	/**
	 * Get the Connection Instance.
	 *
	 * @param void.
	 * @return Connection
	 */
	public static function getInstance()
	{
		if (empty(self::$conn))
		{
			self::$conn = new Connection();
		}
		return self::$conn;
	}
	
	/**
	 * Begin a select operation by returning array result
	 *
	 * @param string $sql    an SQL statement (Select)
	 * @param Array  $param  prepares an SQL statement for execution In this param
	 * @return Array
	 */
	public function query($sql, $param=array())
	{
		$this->count_r++;
		$result = array();
		if (empty($this->r))
		{
			$dns = "mysql:host=".Q::ini('appini/slave_db_host').";dbname=".Q::ini('appini/slave_db_name');
			$this->r = new PDO($dns, Q::ini('appini/slave_db_user'), Q::ini('appini/slave_db_password'));
			$st = $this->r->prepare("set names 'utf8'");
			$st->execute();
		}
		$stmt = $this->r->prepare($sql);
		$stmt->execute($param);
		$stmt->setFetchMode(PDO::FETCH_ASSOC);
		foreach ($stmt as $k => $v)
		{
			$result[$k] = $v;
		}
		return $result;
	}
	/**
	 * Execute the query from a pdo instance.
	 *
	 * @param string $sql    an SQL statement (Insert Update Delete)
	 * @param Array  $param  prepares an SQL statement for execution In this param
	 * @return int   updated the record count
	 */
	public function execute($sql, $param=array(), $affectedRows=false)
	{
		$this->count_w++;
		if (empty($this->w))
		{    
		    /*
			$dns = "mysql:host=".Q::ini('appini/master_db_host').";dbname=".Q::ini('appini/master_db_name');
			$this->w = new PDO($dns, Q::ini('appini/master_db_user'), Q::ini('appini/master_db_password'));
			$st = $this->w->prepare("set names 'utf8'");
			$st->execute();
			*/
		    $this->w = $this->getPdoWrite();
		}
		$stmt = $this->w->prepare($sql);
		$result = $stmt -> execute($param);
		if($affectedRows)
			return $stmt->rowCount();
		return $result;
	}
	/**
	 * Get the number of Read connection 
	 *
	 * @param void
	 * @return Int
	 */
	public function getNumOfRead()
	{
		return $this->count_r;
	}
	/**
	 * Get the number of Write connection 
	 *
	 * @param void
	 * @return Int
	 */
	public function getNumOfWrite()
	{
		return $this->count_w;
	}
	
	/**
	 * Get the PDO Instance.
	 *
	 * @param void
	 * @return Int
	 */
	protected function getPdoWrite() 
	{
	    if (empty($this->w))
	    {
			$dns = "mysql:host=".Q::ini('appini/master_db_host').";dbname=".Q::ini('appini/master_db_name');
			$dbh = new PDO($dns, Q::ini('appini/master_db_user'), Q::ini('appini/master_db_password'));
			$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			$dbh->prepare("set names 'utf8'")->execute();
	    }
	    return $dbh;
	}
	
	/**
	 * Get the last inserted id 
	 * 
	 */
	public function getLastInsert(){
		if($this->w){
			return	$this->w->lastInsertId();
		}else{
			return false;
		}
	}
	
	/**
	 * Begin a transaction, turning off autocommit 
	 *
	 * @param void
	 * @return Boolean if success return true else return false
	 */
	public function beginTransactionW()
	{
		if (empty($this->w))
		{    
		    $this->w = $this->getPdoWrite();
		}
		// Begin a transaction, turning off autocommit 
		return $this->w->beginTransaction();
	}
	
	/**
	 * Commit the changes  
	 *
	 * @param void
	 * @return Boolean if success return true else return false
	 */
	public function commitW()
	{
		if (empty($this->w))
		{    
		    $this->w = $this->getPdoWrite();
		}
		// commit the changes
		return $this->w->commit();
	}
	
	/**
	 * Commit the changes  
	 *
	 * @param void
	 * @return Boolean if success return true else return false
	 */
	public function rollBackW()
	{
		if (empty($this->w))
		{    
		    $this->w = $this->getPdoWrite();
		}
		// Recognize mistake and roll back changes 
		return $this->w->rollBack();
	}
	
	/**
	 * Execute an SQL statement
	 * @param string $sql
	 * @return the number of affected rows 
	 */
	public function exec($sql) {
		if (empty($this->w))
		{    
		    $this->w = $this->getPdoWrite();
		}
		$this->w->exec($sql);
	}
}
?>